---------------------------------------------------------------------
-- 公会模块

-- db.unionSignIn               最近一次公会签到的0点时间戳
---------------------------------------------------------------------

local Lang = require("common.Lang")
local FilterUtil = require("common.FilterUtil")
local UnionDBLogic = require("union.UnionDBLogic")
local UnionExcel = require("excel.union")
local MailManager = require("mail.MailManager")
local MailExcel = require("excel.mail")
local RoleDBLogic = require("role.RoleDBLogic")
local Msg = require("core.Msg")
local Broadcast = require("broadcast.Broadcast")
local ObjHuman = require("core.ObjHuman")
local Util = require("common.Util")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local CombatLogic = require("combat.CombatLogic")
local CombatDefine = require("combat.CombatDefine")
local HeroGrid = require("hero.HeroGrid")
local ChatUnion = require("chat.ChatUnion")
local ChatHandler = require("chat.Handler")
local Grid = require("bag.Grid")
local UnionEctypeLogic = require("union.UnionEctypeLogic")
local UnionWarLogic = require("union.UnionWarLogic")
local UnionWarDBLogic = require("union.UnionWarDBLogic")
local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local RoleLogic = require("role.RoleLogic")
local UnionDefine = require("union.UnionDefine")
local MonsterExcel = require("excel.monster")
local VipLogic = require("vip.VipLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local UnionDonateLogic = require("union.UnionDonateLogic")
local UnionLivenessLogic = require("union.UnionLivenessLogic")
local MailDefine = require("mail.MailIdDefine")
local RoleAttr = require("role.RoleAttr")
local Timer = require("core.Timer")
local BillboardDB = require("billboard.BillboardDB")
local InnerMsg = require("core.InnerMsg")

local FieldsMember = {lastLoginTime = 1}
local FieldsUnionOffline = {presidentUuid = 1}
local FieldsRoleOffline = {lastLogoutTime = 1, lv = 1,identity = 1, name = 1}

local FakeHuman = {}

local CREATEUNION_NEED_VIPLV = 2                    -- 创建公会需要VIP等级
local CREATEUNION_NEED_LV = 35                      -- 创建公会需要等级
local CREATEUNION_NEED_ZUANSHI = 100                -- 创建公会花费
local EXPEL_CNT_MAX = 10                            -- 每日踢人上限
local POST_OFFICIAL_MAXCNT = 3                      -- 官员上限
local UNION_CHANGE_CD = 86400                       -- 公告修改CD
local SIGNIN_GIVE_UNIONCOIN = 50                    -- 签到给与公会币
local CHANGENAME_NEED_ZUANSHI = 500                -- 改名花费
local UNION_NAME_LEN_MAX = 18                       -- 公会名字最大长度
local UNION_NAME_LEN_MIN = 3                        -- 公会名字最小长度
local UNION_ALL_MAIL_MAX_CNT = 10                   -- 每日邮件上限
local UNION_AUTO_PRESIDENT_TIME = 3 * 86400         -- 会长离线x秒自动转让位置
local RECRUIT_COST_VALUE = 18                      -- 招募花费
local UNION_OP_IMPEACH_PRESIDENT = 300              -- 弹劾会长操作花费

-- 公会成员管理
local UNION_MEM_EXPEL = 1               -- 踢出玩家
local UNION_MEM_SET_POST = 2            -- 设置管理员
local UNION_MEM_CHANGE_PRESIDENT = 3    -- 转让会长

UNION_CHANGE_OP_1 = 1     -- 离开公会
UNION_CHANGE_OP_2 = 2     -- 加入公会
UNION_CHANGE_OP_3 = 3     -- 解散公会
-------------------------------------- db -----------------------------------------------------
-- 插入公会日志
function addUnionLog(unionUuid, logType, name,classify,param)
    if not logType then return end
    local cf = UnionExcel.log[logType]
    if not cf then return end
    local now = os.time()
    local date = os.date("*t", now)
    local content = Util.format(cf.content, date.month, date.day, date.hour, date.min, name,param)
    UnionDBLogic.addLog(unionUuid, content,classify)
end

-- 发送到公会
function send2Union(msg, union,eUuid)
    if not union then return end

    for uuid in pairs(union.member) do
        local human = ObjHuman.onlineUuid[uuid]
        if human and human.fd and uuid ~= eUuid then
            Msg.send(msg, human.fd)
        end
    end
end

------------------------------------------ msg -----------------------------------------------
local function getUnionConfig(unionLv)
    local unionLv = math.min(unionLv, #UnionExcel.union)
    return UnionExcel.union[unionLv]
end

-- 封装公会基础信息结构体
function fontUnionMsg(net, union, uuid)
    local lv = math.min(union.lv, #UnionExcel.union)
    local config = UnionExcel.union[lv]

    net.unionIdentity = union.id 
    net.unionUuid = union._id
    net.name = union.name or ""
    net.maxCnt = config.maxCnt
    net.curCnt = union.curCnt
    net.bannerID = union.bannerID
    net.needLv = union.needLv or 0
    net.notice = union.notice
    net.lv = lv
    net.exp = union.exp
    net.maxExp = config.exp

    local presidentDB = RoleDBLogic.getDb(union.presidentUuid, "name")
    net.presidentName = presidentDB and presidentDB.name or ""
    net.isApply = 0
    if uuid and UnionDBLogic.isApply(union, uuid) then
        net.isApply = 1
    end
end

-- 封装公会成员信息结构体
function fontUnionMember(net, uuid, member)
    local FieldsMember = {unionDonate = 1,unionLiveness = 1,lastLogoutTime = 1,dailyBanggong = 1,totalBanggong = 1}
    RoleLogic.makeRoleBaseFields(FieldsMember)
    local db, online = RoleDBLogic.getDb(uuid, FieldsMember)
    RoleLogic.makeRoleBase(db, net.roleBase)
    net.post = member.post
    net.inUnionWar = 0 --UnionWarDBLogic.isCommonSign(uuid) and 1 or 0
    net.lastLogoutTime = 0

    -- 成员捐赠
    net.todayDonate = db.dailyBanggong or 0

    net.totalDonate = db.totalBanggong or 0

    -- 成员活跃度
    if db.unionLiveness == nil then
        net.liveLv = 0
    else
        net.liveLv = db.unionLiveness.lv
    end

    if not online then
        if db.lastLogoutTime == nil then
            -- 刚刚离线，未保存离线时间
            net.lastLogoutTime = 1
        else
            net.lastLogoutTime = os.time() - (db and db.lastLogoutTime or 0)
        end
    end
end

-- 发送公会信息
function sendUnionQuery(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)    
    if not union then return end

    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member then return end

    
    -- 因为客户端要知道会长信息，为了客户端方便，把会长放在首位
    local presidentMember = union.member[union.presidentUuid]

    -- 由于逻辑错误导致副会长将会长踢出公会，这里做个判断修复数据
    -- 如果会长数据为nil,设置第一个成员为会长
    if not presidentMember then
        for k,v in pairs(union.member) do
            UnionDBLogic.setPresident(union, k)
            union = UnionDBLogic.getUnion(human.db.unionUuid)    
            presidentMember = union.member[union.presidentUuid]
            break
        end
    end

    local msgRet = Msg.gc.GC_UNION_QUERY
    msgRet.post = member.post
    msgRet.logDot = hasLog(human, union) and 1 or 0
    msgRet.leaveUnion = human.db.leaveUnionLimit and 1 or 0
    fontUnionMsg(msgRet.unionMsg, union)

    msgRet.unionMember[0] = 1
    fontUnionMember(msgRet.unionMember[1], union.presidentUuid, presidentMember)
    for uuid, member in pairs(union.member) do
        if uuid ~= union.presidentUuid then
            if msgRet.unionMember[0] >= #msgRet.unionMember then
                break
            end
            msgRet.unionMember[0] = msgRet.unionMember[0] + 1
            fontUnionMember(msgRet.unionMember[msgRet.unionMember[0]], uuid, member)
        end
    end
    msgRet.hasApply = dot(human) and 1 or 0
    Msg.send(msgRet, human.fd)
    return true
end

-- 发送公会变更
function sendUnionChange(union, uuid)
    local msgRet = Msg.gc.GC_UNION_CHANGE_MSG
    fontUnionMsg(msgRet.unionMsg, union)

    if uuid then
        local human = ObjHuman.onlineUuid[uuid]
        if human and human.fd then
            Msg.send(msgRet, human.fd)  
        end
    else
        send2Union(msgRet, union)
    end    
end

-- 公推推荐列表/查询返回列表
function sendRecommandList(human, rtype, list)
    local msgRet = Msg.gc.GC_UNION_RECOMMEND
    msgRet.type = rtype
    msgRet.unionMsg[0] = math.min(list and #list or 0, #msgRet.unionMsg)
    for i = 1, msgRet.unionMsg[0] do
        fontUnionMsg(msgRet.unionMsg[i], list[i], human.db._id)
    end
    Msg.send(msgRet, human.fd)
end

-- 给加入公会的成员返回公会信息(考虑删除)
function sendUnionMsg(uuid, union)
    if not union then return end
    local human = ObjHuman.onlineUuid[uuid]
    if not human or not human.fd then return end

    local msgRet = Msg.gc.GC_UNION_MSG
    msgRet.unionIdentity = union.id
    msgRet.unionUuid = union._id 
    msgRet.unionName = union.name 
    msgRet.bannerID = union.bannerID
    Msg.send(msgRet, human.fd)
end

-- 成员信息变化
function sendMemberUpdate(union, uuid)
    local msgRet = Msg.gc.GC_UNION_AGREE_JOIN_UPDATE_MEMBER
    msgRet.unionMember[0] = 0
    for uuid, member in pairs(union.member) do
        if msgRet.unionMember[0] >= #msgRet.unionMember then
            break
        end
        msgRet.unionMember[0] = msgRet.unionMember[0] + 1
        fontUnionMember(msgRet.unionMember[msgRet.unionMember[0]], uuid, member)
    end
    if uuid then
        local human = ObjHuman.onlineUuid[uuid]
        if human and human.fd then
            Msg.send(msgRet, human.fd)  
        end
    else
        send2Union(msgRet, union)
    end   
end

-- 申请列表
function sendApplyMsg(human, union)
    if not union then return end     
    local msgRet = Msg.gc.GC_UNION_APPLY_MSG
    msgRet.applyMsg[0] = 0
    if union.apply then
        for uuid in pairs(union.apply) do
            if msgRet.applyMsg[0] >= #msgRet.applyMsg then
                break
            end

            local applyNet = msgRet.applyMsg[msgRet.applyMsg[0] + 1]
            if RoleLogic.getRoleBaseByUuid(uuid, applyNet.roleBase) then
                applyNet.flag = 1
                msgRet.applyMsg[0] = msgRet.applyMsg[0] + 1
            end
        end
    end
    Msg.send(msgRet, human.fd)
end

-- 查询公会，有公会返回公会信息，没公会返回推荐列表
function unionQuery(human)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1001, true)  then
        return
    end

    if sendUnionQuery(human) then -- 公会基础信息
        return
    end 

    -- 推荐列表
    local recommandList = UnionDBLogic.getRecommendList()
    sendRecommandList(human, UnionDefine.RECOMMEND_TYPE_RANDOM, recommandList)
end

-- 查找公会
function findUnion(human, unionName)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1001, true) then
        return false
    end

    if UnionDBLogic.getUnion(human.db.unionUuid) then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_ONE)
    end

    local unionList = UnionDBLogic.getUnionByNameRegex(unionName)
    local union = UnionDBLogic.getUnion(unionName)
    if union then
        unionList = unionList or {}
        table.insert(unionList, 1, union)
    end
    sendRecommandList(human, UnionDefine.RECOMMEND_TYPE_FIND, unionList)
    if not unionList or #unionList < 1 then
        Broadcast.sendErr(human, Lang.UNION_IS_UNREAL)
    end
end

-- 判断公会名是否合法
local function checkUnionName(human, unionName)
    -- 如果unionName是nil   公会名不能为空
    if not unionName then 
        return Broadcast.sendErr(human, Lang.UNION_FAIL_NAME_NIL)
    end
    local nameLen = string.len(unionName)
    -- 如果公会名长度小于公会名最小长度  公会名过短
    if nameLen < UNION_NAME_LEN_MIN then        
        return Broadcast.sendErr(human, Lang.UNION_FAIL_NAME_LEN1)
    end
    -- 如果公会名长度大于公会名最小长度  公会名过长
    if nameLen > UNION_NAME_LEN_MAX then        
        return Broadcast.sendErr(human, Lang.UNION_FAIL_NAME_LEN2)
    end
    -- 如果公会名中包含非法字符				公会名中有非法字符
    if unionName ~= FilterUtil.filterName(unionName) then        
        return Broadcast.sendErr(human, Lang.UNION_FAIL_NAME_FILTER)
    end
    -- 公会名已经存在
    if UnionDBLogic.isNameExistInDB(unionName) then        
        return Broadcast.sendErr(human, Lang.UNION_FAIL_NAME_DUPLICATE)
    end
    return true
end

-- 创建工会
function createUnion(human, unionName, bannerID, notice, needLv, needAgree)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1001, true)  then
        return
    end

    -- 需要VIP等级
    --[[
    local vipLv = VipLogic.getVipLv(human)
    if vipLv < CREATEUNION_NEED_VIPLV and human.db.lv < CREATEUNION_NEED_LV then
        return Broadcast.sendErr(human, Util.format(Lang.ROLE_VIP_ERROR, CREATEUNION_NEED_VIPLV, CREATEUNION_NEED_LV)) 
    end
    ]]
   

    if UnionDBLogic.getUnion(human.db.unionUuid) then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_ONE)
    end

    if not checkUnionName(human, unionName) then return end
    if not ObjHuman.checkRMB(human, CREATEUNION_NEED_ZUANSHI) then
        return
	end

    local now = os.time()
    if human.db.leaveUnionLimit ~= nil and now < human.db.leaveUnionLimit then
        return Broadcast.sendErr(human, Lang.UNION_LEAVE_TIME_NO_ENOUGH)
    end

    ObjHuman.decZuanshi(human, -CREATEUNION_NEED_ZUANSHI, "createUnion")

    bannerID = bannerID or 1
    notice = notice or ""
    local union = UnionDBLogic.addUnion(human, unionName, bannerID, notice, needLv, needAgree)
    if not union then return end

    human.db.unionUuid = union._id
    ObjHuman.save(human)
    
    addUnionLog(union._id, 1, human.db.name,UnionDefine.UNION_LOG_CLASSIFY_BASE)    
    sendUnionQuery(human)
    Broadcast.sendErr(human, Lang.UNION_CREATE_SUCCESS)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1001)

    unionChangeOp(UNION_CHANGE_OP_2, human.db._id, union._id)
end

-- 离开公会回调
function onLeaveUnion(unionUuid, uuid, logType, mailId)
    local db = RoleDBLogic.getDb(uuid)
    if db then
        FakeHuman.db = db 
        db.unionUuid = nil
        RoleDBLogic.saveRole(db)
        addUnionLog(unionUuid, 4, db.name,UnionDefine.UNION_LOG_CLASSIFY_BASE) 
        db.dailyBanggong = 0
        db.totalBanggong = 0
        if mailId then
            local title = MailExcel.mail[mailId].title
            local content = MailExcel.mail[mailId].content
            local senderName = MailExcel.mail[mailId].senderName
            MailManager.add(MailManager.SYSTEM, uuid, title, content, nil, senderName)    
        end
    end

    local human = ObjHuman.onlineUuid[uuid]
    if human and human.fd then
        Msg.send(Msg.gc.GC_UNION_LEAVE, human.fd)
        RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1001)
    end

    if mailId  and mailId == MailDefine.MAIL_ID_UNION_DISMISS then
        unionChangeOp(UNION_CHANGE_OP_3, uuid, unionUuid)
    else
        unionChangeOp(UNION_CHANGE_OP_1, uuid, unionUuid)
    end
end

-- 解散公会
function dismissUnion(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    local unionUuid = human.db.unionUuid
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    if union.presidentUuid ~= human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    if union.curCnt > 1 then
        return Broadcast.sendErr(human, Lang.UNION_HAS_MEMBER)
    end
    local warState = UnionWarLogic.getState()
    if warState > UnionWarLogic.STATE1 then -- 公会战期间
        return Broadcast.sendErr(human, Lang.UNION_IS_WARRING)
    end

    UnionDBLogic.delUnion(union._id)
    onLeaveUnion(union._id, human.db._id, nil, MailDefine.MAIL_ID_UNION_DISMISS) 
    if not human.db.leaveUnionLimit then
        human.db.leaveUnionLimit = 0
    else
        human.db.leaveUnionLimit = os.time() + 8*60*60
    end
    Broadcast.sendErr(human, Lang.UNION_DISMISS_SUCCESS)  
    BillboardDB.dismissUnion(unionUuid) 
    UnionWarDBLogic.dismissUnion(unionUuid) 
end

-- 申请加入公会
function applyJoinUnion(human, unionUuid)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1001, true)  then
        return
    end    

    local now = os.time()
    if human.db.leaveUnionLimit ~= nil and now < human.db.leaveUnionLimit then
        return Broadcast.sendErr(human, Lang.UNION_LEAVE_TIME_NO_ENOUGH)
    end

    if UnionDBLogic.getUnion(human.db.unionUuid) then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_JOIN_OTHER)
    end

    local union = UnionDBLogic.getUnion(unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_IS_UNREAL)
    end

	if (union.needLv or 0) > human.db.lv then
        return Broadcast.sendErr(human, Lang.UNION_IS_NEED_LV)	
	end
	
    local config = getUnionConfig(union.lv)
 --   if  union.curCnt >= config.maxCnt then -- 人数满了
 --       return Broadcast.sendErr(human, Lang.UNION_IS_FULL)
 --   end
	
    local isJoin = false
	if union.needAgree == 1 or union.curCnt >= config.maxCnt then
		UnionDBLogic.addApply(union, human.db._id)	

        local msgRet = Msg.gc.GC_UNION_APPLY_JOIN
        msgRet.unionUuid = unionUuid
        Msg.send(msgRet, human.fd)
        for _,tpHuman in pairs(ObjHuman.onlineUuid) do
            if isPost(tpHuman) and tpHuman.db.unionUuid == unionUuid then
                RoleSystemLogic.onDot(tpHuman, RoleSystemDefine.ROLE_SYS_ID_1005)
            end
        end
	else
		-- 自动同意
		human.db.unionUuid = union._id
        isJoin = true
        ObjHuman.save(human)
        
        UnionDBLogic.addUnionMember(union, human.db._id)
        addUnionLog(union._id, 3, human.db.name,UnionDefine.UNION_LOG_CLASSIFY_BASE)
        sendUnionMsg(human.db._id, union)

        -- 邮件
        local mailID = MailDefine.MAIL_ID_UNION_JOIN
        local title = MailExcel.mail[mailID].title
        local content = Util.format(MailExcel.mail[mailID].content, union.name)
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, human.db._id, title, content, nil, senderName) 

        --unionQuery(human)
        sendMemberUpdate(union)
	end
	
    Broadcast.sendErr(human, Lang.UNION_APPLY_OK)
    if isJoin then
        unionChangeOp(UNION_CHANGE_OP_2, human.db._id, union._id)
    end
end

--  会长同意/拒绝加入公会
function agreeJoinUnion(human, uuid, isArgee)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end

    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    -- 申请不存在
    if not UnionDBLogic.isApply(union, uuid) then
        return Broadcast.sendErr(human, Lang.UNION_APPLY_AGREE_ERR_NONE)
    end
    local isJoin = false
    if isArgee == 1 then
        local config = getUnionConfig(union.lv)
        if union.curCnt >= config.maxCnt then -- 人数满了
            return Broadcast.sendErr(human, Lang.UNION_CNT_IS_OVER)
        end
        UnionDBLogic.delApply(union, uuid)
        local db = RoleDBLogic.getDb(uuid)
        if db == nil then -- 不存在
            return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_ID)
        end
        if UnionDBLogic.getUnion(db.unionUuid) then -- 有公会
            return Broadcast.sendErr(human, Lang.UNION_PLAYER_JOIN_OTHER)
        end  

        db.unionUuid = union._id
        RoleDBLogic.saveRole(db)
        UnionDBLogic.addUnionMember(union, uuid) 
        addUnionLog(union._id, 3, db.name,UnionDefine.UNION_LOG_CLASSIFY_BASE)
        sendUnionMsg(uuid, union)

        -- 邮件
        local mailID = MailDefine.MAIL_ID_UNION_JOIN
        local title = MailExcel.mail[mailID].title
        local content = Util.format(MailExcel.mail[mailID].content, union.name)
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, db._id, title, content, nil, senderName) 

        sendMemberUpdate(union,uuid)
        sendMemberUpdate(union,human.db._id)
        isJoin = true
    else
        UnionDBLogic.delApply(union, uuid)
    end
    sendApplyMsg(human, union)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1005)
    if isJoin then
        unionChangeOp(UNION_CHANGE_OP_2, uuid, union._id)
    end
end

-- 一键拒绝
function oneKeyDisagree(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    UnionDBLogic.resetApply(union)
    sendApplyMsg(human, union)
    RoleSystemLogic.onDot(tpHuman, RoleSystemDefine.ROLE_SYS_ID_1005)
end

-- 会长踢玩家出公会
function expelPlayer(human, uuid)
    if human.db._id == uuid then --不能踢自己
        return Broadcast.sendErr(human, Lang.UNION_OPERATE_FAIL)
    end
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_IS_UNREAL)
    end
    local member = UnionDBLogic.getUnionMember(union, uuid)
    if not member or member.post == UnionDefine.POST_PRESIDENT then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    if UnionDBLogic.getKickCntToday(union) >= EXPEL_CNT_MAX then
        return Broadcast.sendErr(human, Lang.UNION_EXPEL_NUM_MAX_ERROR)
    end
    local tmember = UnionDBLogic.getUnionMember(union, uuid)
    if not tmember then --该玩家不在本公会
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_OTHER)
    end

    UnionDBLogic.delUnionMember(union, uuid, true)
    onLeaveUnion(union._id, uuid, 2, MailDefine.MAIL_ID_UNION_LEAVE)
    sendMemberUpdate(union)
    Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)

    local fakeHuman = ObjHuman.onlineUuid[uuid]
    if fakeHuman and fakeHuman.db then
        RoleAttr.cleanHeroAttrCache(fakeHuman)
    end
   
end

-- 玩家自己离开公会
function leaveUnion(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end

    if union.presidentUuid == human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_LEVEL_ERR_LEADER)
    end

    UnionDBLogic.delUnionMember(union, human.db._id)
    onLeaveUnion(union._id, human.db._id)
    if not human.db.leaveUnionLimit then
        human.db.leaveUnionLimit = 0
    else
        human.db.leaveUnionLimit = os.time() + 8*60*60
    end
    sendMemberUpdate(union)
    Broadcast.sendErr(human, Lang.UNION_LEVEL_SUCCESS)
    if human.db.roleDot and human.db.roleDot.unionLog then
        human.db.roleDot.unionLog = nil
    end
    RoleAttr.cleanHeroAttrCache(human)
end

-- 玩家公会变化
function unionChangeOp(op,  uuid, unionUuid)
    local msgInner =  InnerMsg.lw.LW_ROLE_UNION_OP
    msgInner.op = op
    msgInner.uuid = uuid
    msgInner.unionUuid = unionUuid
    InnerMsg.sendMsg(0, msgInner)
end

-- 设置工会官员
function setPost(human, uuid)
    if human.db._id == uuid then
        return Broadcast.sendErr(human, Lang.UNION_OPERATE_FAIL)
    end
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    if union.presidentUuid ~= human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    local member = UnionDBLogic.getUnionMember(union, uuid)
    if not member then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_OTHER)
    end
    local postCnt = UnionExcel.union[union.lv].postCnt
    local db = RoleDBLogic.getDb(uuid, "name")
    if member.post == UnionDefine.POST_OFFICIAL then 
        -- 取消官员
        UnionDBLogic.setPost(union, uuid, UnionDefine.POST_MEMBER)

        addUnionLog(union._id, 7, db and db.name or "",UnionDefine.UNION_LOG_CLASSIFY_BASE)
        local mailID = MailDefine.MAIL_ID_UNION_BE_MEMBER
        local title = MailExcel.mail[mailID].title
        local content = MailExcel.mail[mailID].content
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, uuid, title, content, nil, senderName)
    else
        if UnionDBLogic.getPostCnt(union, UnionDefine.POST_OFFICIAL) >= postCnt then
            return Broadcast.sendErr(human, Lang.UNION_POST_IS_MAX)
        end
        -- 设置为官员
        UnionDBLogic.setPost(union, uuid, UnionDefine.POST_OFFICIAL)
        
        addUnionLog(union._id, 5, db and db.name or "",UnionDefine.UNION_LOG_CLASSIFY_BASE)
        local mailID = MailDefine.MAIL_ID_UNION_BE_POST
        local title = MailExcel.mail[mailID].title
        local content = MailExcel.mail[mailID].content
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, uuid, title, content, nil, senderName)
    end
    sendMemberUpdate(union)
    Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)
end

-- 更换会长
function changePresident(human, uuid)
    if human.db._id == uuid then
        return Broadcast.sendErr(human, Lang.UNION_OPERATE_FAIL)
    end
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    if union.presidentUuid ~= human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    local member = UnionDBLogic.getUnionMember(union, uuid)
    if not member then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_OTHER)
    end    
    UnionDBLogic.setPresident(union, uuid)
    local db = RoleDBLogic.getDb(uuid, "name")
    addUnionLog(union._id, 6, db.name,UnionDefine.UNION_LOG_CLASSIFY_BASE)
    sendMemberUpdate(union)
    Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)

    -- 发送邮件
    for uuid in pairs(union.member) do
        local mailID = MailDefine.MAIL_ID_UNION_CHANGE_PRE1
        local title = MailExcel.mail[mailID].title
        local content = Util.format(MailExcel.mail[mailID].content, db.name)
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, uuid, title, content, nil, senderName)
    end
end

-- 成员管理
function memberMam(human, uuid, mamType)
    if mamType == UNION_MEM_EXPEL then
        return expelPlayer(human, uuid)
    elseif mamType == UNION_MEM_SET_POST then
        return setPost(human, uuid) 
    elseif mamType == UNION_MEM_CHANGE_PRESIDENT then
        return changePresident(human, uuid)
    else
        return Broadcast.sendErr(human, Lang.UNION_OPERATE_FAIL)
    end
end

-- 设置公告
function setNotice(human, notice)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    if notice == union.notice then
        return Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)
    end    
    if union.noticeTime and (os.time() - union.noticeTime < UNION_CHANGE_CD) then
        local hour = math.floor((UNION_CHANGE_CD - (os.time() - union.noticeTime)) / 60/60)
        local min = math.floor((UNION_CHANGE_CD - (os.time() - union.noticeTime)) / 60) - (hour*60)
        return Broadcast.sendErr(human, Util.format(Lang.UNION_CHANGE_CD_ERROR,  hour,min))
    end
    if notice ~= FilterUtil.filter(notice) then
        return Broadcast.sendErr(human, Lang.UNION_NOTICE_IS_FAIL)
    end
    UnionDBLogic.setNotice(union, notice)    
    sendUnionChange(union)
    Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)
end

-- 查询入会设置
function sendJoinLimitQuery(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end 
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    local msgRet = Msg.gc.GC_UNION_CHANGE_LIMIT_QUERY
    msgRet.needLv = union.needLv or 0
    msgRet.needAgree = union.needAgree or 0
    Msg.send(msgRet, human.fd)
end

-- 修改入会设置
function setJoinLimit(human, needLv, needAgree)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    
    UnionDBLogic.setJoinLimit(union, needLv, needAgree)
    Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)
end

function addUnionExpByItem(human, add)
    if not human.db.unionUuid or human.db.unionUuid == "" then 
        return
    end

    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then return end

    addUnionExp(union, add) 
    UnionDBLogic.updateUnionData(union)
end

-- 添加公会经验
function addUnionExp(union, exp)
    local oldLv = union.lv
    union.exp = union.exp + exp
    while true do 
        local config = UnionExcel.union[union.lv]
        if not config then break end
        if config.exp < 1 then -- 满级
            union.exp = 0
            break
        end
        if union.exp < config.exp then
            break
        end
        union.exp = union.exp - config.exp 
        union.lv = union.lv + 1
    end
end

-- 公会申请查询
function applyQuery(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end    
    sendApplyMsg(human, union)
end

-- 获取改名价格
local function getChangeNameCost(union)
    if not union.nameTime then
        return 0 -- 首次改名免费
    end
    return CHANGENAME_NEED_ZUANSHI
end

-- 改名相关查询 例如改名价格
function sendChangeNameQuery(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end  
    if union.presidentUuid ~= human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end    

    local msgRet = Msg.gc.GC_UNION_CHANGE_NAME_QUERY
    msgRet.needCost = getChangeNameCost(union)
    Msg.send(msgRet, human.fd)
end

-- 公会改名
function changeUnionName(human, name, bannerID)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end  

    if union.presidentUuid ~= human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    if union.nameTime and (os.time() - union.nameTime < UNION_CHANGE_CD) then
        local leftTime = math.ceil((UNION_CHANGE_CD - (os.time() - union.nameTime)) / 60)
        return Broadcast.sendErr(human, Util.format(Lang.UNION_CHANGE_CD_ERROR, leftTime))
    end

    if not checkUnionName(human, name) and name ~= union.name then
        return Broadcast.sendErr(human, Lang.CREATE_UNION_FAIL_NAME)
    end

    local needCost = getChangeNameCost(union)
    if not ObjHuman.checkRMB(human, needCost) then
		return
	end
    ObjHuman.decZuanshi(human, -needCost, "changeUnionName")
    UnionDBLogic.setUnionName(union, name)    
    sendUnionChange(union)
    Broadcast.sendErr(human, Lang.UNION_CHANGE_NAME_SUCCESS)
end

-- 公会改旗帜
function changeUnionBannerID(human,bannerID)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end  

    if union.presidentUuid ~= human.db._id then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    if not UnionExcel.banner[bannerID] then
        return Broadcast.sendErr(human, Lang.UNION_BANNER_ID_ILL)
    end

    UnionDBLogic.setBannerID(union, bannerID)    
    sendUnionChange(union)
    Broadcast.sendErr(human, Lang.UNION_OPERATE_SUCCESS)
end

-- 发送邮件
function sendUnionMail(human, content)
    local msgRet = Msg.gc.GC_UNION_MAIL
    msgRet.flag = 0
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        Msg.send(msgRet, human.fd)
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        Msg.send(msgRet, human.fd)
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end
    local mailCnt = UnionDBLogic.getMailCnt(union)
    if mailCnt >= UNION_ALL_MAIL_MAX_CNT then
        Msg.send(msgRet, human.fd)
        return Broadcast.sendErr(human, Lang.UNION_MAIL_CNT_MAX)
    end
    if content == "" or content ~= FilterUtil.filter(content) then
        return Broadcast.sendErr(human, Lang.MAIL_CONTENT_ERROR)
    end
    union.mailCnt = mailCnt + 1
    union.mailTs = union.mailTs or os.time()
    UnionDBLogic.updateUnionData(union)

    for uuid in pairs(union.member) do
        MailManager.add(MailManager.SYSTEM, uuid, Lang.UNION_MAIL, content, nil, human.db.name, human)
    end    
    Broadcast.sendErr(human, Lang.UNION_SEND_SUCCESS)

    msgRet.flag = 1
    Msg.send(msgRet, human.fd)
end

function hasLog(human, union)
    local time = 0
    if  human.db.roleDot and  human.db.roleDot.unionLog then
        time =  human.db.roleDot.unionLog
    end
    for i = 1, #union.logs do
        local log = union.logs[i]
       
        if log.time > time then
            return true
        end
    end
    return false
end

-- 公会日志
function getLog(human,classify)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end

    local msgRet = Msg.gc.GC_UNION_GET_LOG
    local cnt = 0
    for i = 1, #union.logs do
        local log = union.logs[i]
        if log.classify == classify or classify == 0 then
            cnt = cnt + 1
            msgRet.logMsg[cnt].logMsg = log.content 
        end
        if cnt >= #msgRet.logMsg then
            break
        end
    end
    msgRet.logMsg[0] = cnt
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
    human.db.roleDot = human.db.roleDot or {}
    human.db.roleDot.unionLog = os.time()
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1005)
end

local function getRecruitCost(union)
    if not union.recruit then return 0 end
    return RECRUIT_COST_VALUE
end

-- 招募查询
function sendRecruitQuery(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    local msgRet = Msg.gc.GC_UNION_RECRUIT_QUERY
    msgRet.costValue = getRecruitCost(union)
    Msg.send(msgRet, human.fd)
end

-- 招募宣言
function unionRecruit(human,str)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member or (member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    -- 检查花费
    local costValue = getRecruitCost(union)
    if not ObjHuman.checkRMB(human, costValue) then

        Msg.send(msgRet, human.fd)
        return
    end

    human.chatTime = human.chatTime or {}
    local chatTime = human.chatTime[ChatHandler.CHAT_TYPE_WORLD] or 0
    if chatTime + ChatHandler.CHAT_CD >= Timer.now then
		local cdLeftSec = math.ceil((ChatHandler.CHAT_CD - (Timer.now - chatTime))/1000)
		Broadcast.sendDown(human, Util.format(Lang.CHAT_TIME_SHORT, cdLeftSec))
        return 
    end

    human.worldChatLast = human.worldChatLast or {}
    if human.worldChatLast[ChatHandler.CHAT_TYPE_WORLD] == str then
        Broadcast.sendDown(human, Lang.CHAT_TIME_DUPLICATE)
        return
    end

    ObjHuman.decZuanshi(human, -costValue, "union_recruit")
    if not union.recruit then
        union.recruit = 1
        UnionDBLogic.updateUnionData(union)
    end

    local dec = Util.format(Lang.UNION_RECRUIT_BC, union.lv, union.name)
    ChatUnion.chatUnion(human, ChatHandler.CHAT_TYPE_UNION, str)
    
    Broadcast.sendErr(human, Lang.UNION_SEND_SUCCESS)
end

-- 是否有红点 申请
function dot(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if union == nil then
        return
    end

    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member then return end
    if member.post ~= UnionDefine.POST_PRESIDENT and 
        member.post ~= UnionDefine.POST_OFFICIAL then
        return
    end

    if union.apply == nil then
        return
    end
    return next(union.apply) ~= nil
end

-- 用于显示红点
function isDot(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if union == nil then
		-- 没加入公会 不显示红点
        return
    end

    if dot(human) then
        return true
    end

    if hasLog(human, union) then
        return true
    end

    return nil
end


-- 0点后自动让位
function onHour()
    PRESIDENT_CHECK_FLAG = true
end

-- 自动让位
PRESIDENT_AUTO_LIST = PRESIDENT_AUTO_LIST or nil            -- 自动让位列表
PRESIDENT_CHECK_FLAG = PRESIDENT_CHECK_FLAG or nil          -- 自动让位标记
function checkPresidentOffline()
    if PRESIDENT_AUTO_LIST then return end
    PRESIDENT_CHECK_FLAG = nil
    PRESIDENT_AUTO_LIST = {}
    local lastSevenDays = os.time() - UNION_AUTO_PRESIDENT_TIME
    LuaMongo.find(DB.db_union, nil, FieldsUnionOffline)
    local union2president = {}
    while true do
        local union = {}
        if not LuaMongo.next(union) then
            break
        end
        union2president[union._id] = union.presidentUuid
    end

    for unionUuid, presidentUuid in pairs(union2president) do
        local db, online = RoleDBLogic.getDb(presidentUuid, FieldsRoleOffline)
        if not db or (not online and (db.lastLogoutTime or 0) < lastSevenDays) then
           PRESIDENT_AUTO_LIST[#PRESIDENT_AUTO_LIST + 1] = unionUuid
        end
    end
end

-- 是否可继承会长
local function canBeNewPresident(db, lastSevenDays, online)
    if not db then return end
    if not online and db.lastLogoutTime < lastSevenDays then
        return
    end
    return true
end

-- 比较
local function cmpBeNewMember(db1, db2)
    if not db1 then return end
    if not db2 then return true end
    if db1.lastLogoutTime ~= db2.lastLogoutTime then
        return db1.lastLogoutTime > db2.lastLogoutTime
    end
    return db1.lv > db2.lv
end

-- 自动转让会长
function autoPresidentChange()
    local unionUuid = PRESIDENT_AUTO_LIST[#PRESIDENT_AUTO_LIST]
    if not unionUuid then
        PRESIDENT_AUTO_LIST = nil
        return
    end
    PRESIDENT_AUTO_LIST[#PRESIDENT_AUTO_LIST] = nil

    local union = UnionDBLogic.getUnion(unionUuid)
    if not union then return end

    local lastSevenDays = os.time() - UNION_AUTO_PRESIDENT_TIME
    local newdb = nil 
    for uuid, member in pairs(union.member) do -- 优先挑选管理
        if member.post == UnionDefine.POST_OFFICIAL then
            local db, online = RoleDBLogic.getDb(uuid, FieldsRoleOffline)
            if canBeNewPresident(db, lastSevenDays, online) then
                newdb = db
                break
            end
        end
    end
    if not newdb then
        for uuid, member in pairs(union.member) do -- 再挑普通成员
            if member.post == UnionDefine.POST_MEMBER then
                local db, online = RoleDBLogic.getDb(uuid, FieldsRoleOffline)
                if canBeNewPresident(db, lastSevenDays, online) and
                    not cmpBeNewMember(newdb, db) then
                    newdb = db
                    break
                end
            end
        end
    end
    if not newdb then return end
    -- 设置新会长
    UnionDBLogic.setPresident(union, newdb._id)
    addUnionLog(union._id, 6, newdb.name,UnionDefine.UNION_LOG_CLASSIFY_BASE) 
end

-- 定时检测
function onTimer()
    if PRESIDENT_CHECK_FLAG then
        checkPresidentOffline()
    end
    if PRESIDENT_AUTO_LIST then
        autoPresidentChange()
    end
end

-- 弹劾会长
function impeachPresident(human)
    -- 判断玩家是否有工会
    -- 判断玩家公会是否存在
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if union == nil then
        return
    end

    local db,online = RoleDBLogic.getDb(union.presidentUuid,FieldsRoleOffline)
    
    local lastSevenDays = os.time() - UNION_AUTO_PRESIDENT_TIME
    if online ~= nil or db.lastLogoutTime >= lastSevenDays then
        return -- 弹劾失败
    end

    -- 扣除花费
    local cost = UNION_OP_IMPEACH_PRESIDENT
    if not ObjHuman.checkRMB(human, cost) then
	   return
    end
    ObjHuman.decZuanshi(human, -cost, "abs_answer")

    -- 设置新会长
    UnionDBLogic.setPresident(union, human.db._id)
    addUnionLog(union._id, 14, human.db.name,UnionDefine.UNION_LOG_CLASSIFY_BASE,db.name)
    sendMemberUpdate(union)

    -- 发送系统消息
    -- todo
    -- 发送邮件
    local mailID = MailDefine.MAIL_ID_UNION_CHANGE_PRE2
    local title = MailExcel.mail[mailID].title
    local content = Util.format(MailExcel.mail[mailID].content, human.db.name)
    local senderName = MailExcel.mail[mailID].senderName
    MailManager.add(MailManager.SYSTEM, db._id, title, content, nil, senderName)
end

function getUnionLogMemberDetail(human,type)
    local msgRet = Msg.gc.GC_UNION_LOG_DETAIL_QUERY
    if type == 2 then
        return   -- 临时
        --getCanUnionWarMember(human.db.unionUuid,msgRet)
    elseif type == 3 then
        getCanBossMember(human.db.unionUuid,msgRet)
    elseif type == 4 then
        getCanDonateMember(human.db.unionUuid,msgRet)
    end
    Msg.send(msgRet,human.fd)
end

-- 获得还有挑战工会战次数的玩家
-- todo 等全谈写完工会战，再完成
function getCanUnionWarMember(unionUuid)
    local union = UnionDBLogic.getUnion(unionUuid)    
    if not union then return end

    for uuid, member in pairs(union.member) do
        if uuid ~= union.presidentUuid then
            if msgRet.memberDetail[0] >= #msgRet.memberDetail then
                break
            end
            msgRet.memberDetail[0] = msgRet.memberDetail[0] + 1
            fontUnionMember(msgRet.memberDetail[msgRet.memberDetail[0]], uuid, member)
        end
    end
end

-- 获得还有捐献次数的玩家
function getCanDonateMember(unionUuid,net)
    local union = UnionDBLogic.getUnion(unionUuid)    
    if not union then return end

    local maxCnt = 0
    local leftCnt = 0
    local len = 0
    local maxLen = #net.memberDetail
    for uuid, member in pairs(union.member) do
        maxCnt= maxCnt + 1
        local db = RoleDBLogic.getDb(uuid)
        if db.todayDonate ~= 0 then
            if len >= maxLen then
                break
            end
            leftCnt = leftCnt + 1
            len = len + 1
            fontUnionMember(net.memberDetail[len], uuid, member)
        end
    end
    net.memberDetail[0] = len
    net.maxCnt = maxCnt
    net.leftCnt = leftCnt
end

-- 获得还有挑战工会boss次数的玩家
-- todo 等全谈写完工会boss，再完成
function getCanBossMember(unionUuid,net)
    local union = UnionDBLogic.getUnion(unionUuid)    
    if not union then return end

    local maxCnt = 0
    local leftCnt = 0
    local len = 0
    local maxLen = #net.memberDetail
    for uuid, member in pairs(union.member) do
        maxCnt= maxCnt + 1
        local db = RoleDBLogic.getDb(uuid)
        if db.ectypeCnt == nil or db.ectypeCnt < UnionEctypeLogic.FIGHT_MAX_CNT then
            if len >= maxLen then
                break
            end
            leftCnt = leftCnt + 1
            len = len + 1
            fontUnionMember(net.memberDetail[len], uuid, member)
        end
    end
    net.memberDetail[0] = len
    net.maxCnt = maxCnt
    net.leftCnt = leftCnt
end

function isPost(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if union == nil then
        return
    end

    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member then return end
    if member.post == UnionDefine.POST_PRESIDENT or 
        member.post == UnionDefine.POST_OFFICIAL then
        return true
    end
    return nil
end

function cancelApply(human,unionUuid)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1001, true)  then
        return
    end    

    if UnionDBLogic.getUnion(human.db.unionUuid) then
        return
    end

    local union = UnionDBLogic.getUnion(unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_IS_UNREAL)
    end

	UnionDBLogic.delApply(union, human.db._id)	

    for _,tpHuman in pairs(ObjHuman.onlineUuid) do
        if isPost(tpHuman) and tpHuman.db.unionUuid == unionUuid then
            RoleSystemLogic.onDot(tpHuman, RoleSystemDefine.ROLE_SYS_ID_1005)
        end
    end
end